from tkinter import *
from tkinter.messagebox import *
import threading,socket,datetime
from win32api import GetSystemMetrics#需要下载pywin32然后才能导入该包
class chat_client():
    def __init__(self,host,port):#初始化socket对象
        self.host=host
        self.port=port
        screenX=GetSystemMetrics(0)#获取屏幕宽度
        screenY=GetSystemMetrics(1)#获取屏幕高度
        self.window_indexX=screenX/2-screenX/4
        self.window_indexY=screenY/2-screenY/4
    def draw_login(self):#绘制登录窗口
        self.login_root=Tk()#实例化空窗口
        root=self.login_root
        root.title('ICHAT - 登录')#赋值title标题
        root.geometry('+%d+%d'%(self.window_indexX,self.window_indexY))#绘制窗口的初始位置
        #创建登陆框各类元素
        Label(root,text='账号').grid(row=1,column=0,padx=5,pady=5)
        Label(root,text='密码').grid(row=2,column=0,padx=5,pady=5)
        self.login_username_entry=Entry(root)#用户输入框
        self.login_password_entry=Entry(root)#密码输入框
        signup_button=Button(root,text='注册账号',width=8,height=2,command=self.enter_signup)#注册按钮
        login_button=Button(root,text='登录',width=8,height=2,command=self.login)#登录按钮
        #排版
        self.login_username_entry.grid(row=1,columnspan=2,column=1,padx=5,pady=5)
        self.login_password_entry.grid(row=2,columnspan=2,column=1,padx=5,pady=5)
        signup_button.grid(row=3,column=1,padx=5,pady=5)
        login_button.grid(row=3,column=2,padx=5,pady=5)
        root.resizable(False, False)#关闭可拉伸窗口
        root.mainloop()#窗口循环
    def draw_signup(self):#绘制注册窗口
        self.signup_root=Tk()#实例化空窗口
        root=self.signup_root
        root.title('ICHAT - 注册账号')#赋值title标题
        root.geometry('+%d+%d'%(self.window_indexX,self.window_indexY))#绘制窗口位置
        #创建各类注册框元素
        Label(root,text='昵称').grid(row=0,column=0,padx=5,pady=5)
        Label(root,text='账号').grid(row=1,column=0,padx=5,pady=5)
        Label(root,text='密码').grid(row=2,column=0,padx=5,pady=5)
        Label(root,text='确认密码').grid(row=3,column=0,padx=5,pady=5)
        self.signup_nick_entry=Entry(root)#昵称输入框
        self.signup_username_entry=Entry(root)#账号输入框
        self.signup_password_entry=Entry(root)#密码输入框
        self.sign_confirm_password_entry=Entry(root)#确认密码输入框
        ok_button=Button(root,text='确认',width=8,height=2,command=self.signup)#确认按钮
        cancel_button=Button(root,text='取消',width=8,height=2,command=self.cancel_signup)#取消按钮
        #排版
        self.signup_nick_entry.grid(row=0,columnspan=2,column=1,padx=5,pady=5)
        self.signup_username_entry.grid(row=1,columnspan=2,column=1,padx=5,pady=5)
        self.signup_password_entry.grid(row=2,columnspan=2,column=1,padx=5,pady=5)
        self.sign_confirm_password_entry.grid(row=3,columnspan=2,column=1,padx=5,pady=5)
        ok_button.grid(row=4,column=1,padx=5,pady=5)
        cancel_button.grid(row=4,column=2,padx=5,pady=5)
        root.resizable(False, False)#关闭可拉伸窗口
        root.mainloop()#窗口循环
    def draw_chat_room(self):#绘制聊天窗口
        self.chat_room_root=Tk()#实例化空窗口
        root=self.chat_room_root
        root.title('ICHAT - 多人聊天室')#赋值title标题
        root.geometry('+%d+%d'%(self.window_indexX,self.window_indexY))#绘制窗口位置
        #定义各个窗口
        self.chat_room_output_msg_text=Text(root,width=60,height=24,state=DISABLED,wrap=CHAR)#聊天输出框
        self.chat_room_input_msg_text=Text(root,width=60,height=8)#输入框
        self.chat_room_friends_list=Text(root,width=20,height=38,state=DISABLED)#好友列表
        ad_left_bottom=Frame(root,width=220)#广告区域
        Message(ad_left_bottom,text='ICHAT 广告赞助区域')#广告信息
        close_chat_room_button=Button(root,text='关闭',width=10,height=2,command=self.close_chat_room)#退出按钮
        send_msg_button=Button(root,text='发送',width=10,height=2,command=self.send_msg)#发送消息按钮
        #使用grid排版会话窗口
        self.chat_room_output_msg_text.grid(row=0,column=0,columnspan=3,padx=5,pady=5)#排版聊天输出框
        self.chat_room_input_msg_text.grid(row=1,column=0,columnspan=3,padx=5,pady=5)#排版输入框
        self.chat_room_friends_list.grid(row=0,column=3,rowspan=3,padx=5,pady=5)#排版好友列表
        ad_left_bottom.grid(row=2,column=0,padx=5,pady=5)#排版广告框
        close_chat_room_button.grid(row=2,column=1,padx=5,pady=5)#排版关闭按钮
        send_msg_button.grid(row=2,column=2,padx=5,pady=5)#排版发送消息按钮
        root.resizable(False, False)#关闭可拉伸窗口
        root.mainloop()
    def warning_msg_box(self,msg):#弹出警告窗
        showwarning(title="错误信息!!!",message=msg)
    def run(self):#运行
        self.draw_login()
    def enter_signup(self):#进入注册界面
        self.login_root.destroy()#销毁登录窗口
        self.draw_signup()#绘制注册窗口
    def cancel_signup(self):#退出注册界面，并返回登录界面
        self.signup_root.destroy()#销毁注册窗口
        self.draw_login()#绘制登录窗口
    def signup(self):#注册方法
        signup_nick=self.signup_nick_entry.get()#获取昵称输入框的信息
        signup_username=self.signup_username_entry.get()#获取账号输入框的信息
        signup_password=self.signup_password_entry.get()#获取密码输入框的信息
        sign_confirm_password=self.sign_confirm_password_entry.get()#获取确认密码输入框的信息
        if signup_password!=sign_confirm_password:#判断两次密码是否一致
            self.warning_msg_box("confirm password error!!!")
        else:
            client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#创建客户端socket
            client.connect((self.host,self.port))#连接服务器
            client.send(("1:"+signup_nick+":"+signup_username+":"+signup_password).encode('utf-8'))#发送第一条消息，该消息为注册消息
            msg=client.recv(1024)#接收注册返回信息
            msg=msg.decode()
            if msg=="signup success":#判断服务器返回信息是否为注册成功
                showinfo(message="恭喜！！！注册成功！！！欢迎使用ICHAT多人聊天室")
                self.signup_root.destroy()#销毁注册窗口
                self.draw_login()#绘制登录窗口
            else:
                self.warning_msg_box(msg)#弹出服务器返回的错误信息
        self.signup_password_entry.delete('0',END)#清除密码框信息
        self.sign_confirm_password_entry.delete('0',END)#清除确认密码框信息
    def login(self):#登录方法
        username=self.login_username_entry.get()#取得用户输入的username
        password=self.login_password_entry.get()#取得用户输入的password
        self.client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#创建客户端socket
        client=self.client
        client.connect((self.host,self.port))#连接服务器
        client.send(("2:"+username+":"+password).encode('utf-8'))#发送第一条消息，该消息为用户登录信息
        msg=client.recv(1024)#接收登录返回信息
        msg=msg.decode()
        if msg=="login success":#判断服务器返回信息是否为登录成功
            self.login_root.destroy()#销毁登录窗口
            self.get_msg_thread=threading.Thread(target=self.get_msg)#创建用户消息收发线程
            self.get_msg_thread.start()#开启用户消息收发线程
            self.draw_chat_room()#绘制聊天室窗口
        else:
            self.warning_msg_box(msg)#弹出警告窗，显示服务器端返回的错误信息
    def send_msg(self):#发送消息
        msg=self.chat_room_input_msg_text.get('0.0',END)#获取聊天框中的文本信息
        self.chat_room_output_msg_text['state']='normal'#设置消息框为可写入
        data_now=str(datetime.datetime.now()).split(" ")[1].split(".")[0]#获取当前时间
        self.chat_room_output_msg_text.insert(END,data_now+"\n",'blue')#打印当前时间
        self.chat_room_output_msg_text.insert(END, msg+"\n",'blue')#在最后写入接收到的消息
        self.chat_room_output_msg_text['state']='disable'#设置消息框为不可写入
        self.client.send(msg.encode('utf-8'))#发送消息至服务器
        self.chat_room_input_msg_text.delete('0.0',END)#清除聊天框中的文本信息
    def get_msg(self):#接收消息
        while True:
            try:
                msg=self.client.recv(1024)#接收服务器消息
                self.chat_room_output_msg_text['state']='normal'#设置消息框为可写入
                data_now=str(datetime.datetime.now()).split(" ")[1].split(".")[0]#获取当前时间
                self.chat_room_output_msg_text.insert(END,data_now+"\n")#打印当前时间
                self.chat_room_output_msg_text.insert(END, msg.decode()+"\n")#在最后写入接收到的消息
                self.chat_room_output_msg_text['state']='disable'#设置消息框为不可写入
            except:break
    def close_chat_room(self):#关闭聊天室
        self.client.close()#关闭客户端连接，如果先关闭客户端连接，会导致聊天窗口一直等待客户端收发消息线程结束，造成假死状态
        self.chat_room_root.destroy()#销毁聊天室窗口
def main():
    host='192.168.0.78'
    port=9999
    cc=chat_client(host,port)
    cc.run()
if __name__=='__main__':
    main()